<template>

    <div
      v-loading="loading"
      @dblclick="onClick"
      element-loading-background="rgba(0, 0, 0, 0)"
      id="pcdcontainer"
    
    >
  
  </div>
  
  
  </template>
  
  <script>
  import * as THREE from "three";
  import {Scene, PerspectiveCamera, WebGLRenderer, DirectionalLight} from 'three';
  import { PCDLoader } from "three/examples/jsm/loaders/PCDLoader.js";
  import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
  import { FormItem } from "element-ui";
  
  
  export default {
    props: {
      //上传pcd文件路径
      pcdUrl: {
        type: String,
        // required: true
      },
      //颜色控制
      color: {
        type: Number,
        // required: true
      },
      //已标记点集合
      markPoints:{
        type:Array
      },
      identifying:{
        type:Boolean
      },
      deleteFlag:{
        type:Boolean
      },
      //判断是否为新增双击
      isAdd:{
        type:Boolean
      }
    },
    created () {
      this.localMarkPoints = this.markPoints.slice();
      this.init()
      this.mpoint()
      this.delete()
      console.log( this.localMarkPoints)
      // this.localMarkPoints = this.markPoints.slice();
    },
    data () {
      return {
        localMarkPoints:this.markPoints,
        clickedPointIndex :-1,
        elem: null,
        scene: null,
        camera: null,
        renderer: null,
        loader: null,
        controls: null,
        mesh: null,
        animationId: null,
        pointcloud:{},
        pointsMaterial:new THREE.PointsMaterial({ color: 0xff0000, size: 0.05 }),
        selectedPointMaterial: new THREE.PointsMaterial({ color: 0x00ff00, size: 0.1 }),
        selectedPoint:null,
        clock: new THREE.Clock(),
        mouse: new THREE.Vector2(1, 1),
        client: { clientX: 0, clientY: 0 },
        loading: true,
        line:new THREE.LineBasicMaterial({ color: 0x0000ff }),
      }
    },
    beforeMount () {
  
    },
    async  mounted () {
      // this.localMarkPoints = this.markPoints.slice();
      await this.init()
      //标记点加载渲染
      await this.mpoint()
      await this.cancel()
      await this.delete()
      this.localMarkPoints = this.markPoints.slice();
      console.log( this.localMarkPoints)
    },
    methods: {
  
      async init () {
        let elem = document.getElementById('pcdcontainer');//获取要渲染的Dom
        // 相机
        this.camera = new THREE.PerspectiveCamera(
          30, // 视野
          elem.clientWidth / elem.clientHeight, // 纵横比
          0.1, // 近平面
          1000 // 远平面
        );
  
        this.renderer = new THREE.WebGLRenderer({
          antialias: true,
          alpha: true
        });
        // this.renderer.setClearColor(new THREE.Color(0x303030)); // 背景色
        this.renderer.setClearColor(new THREE.Color(0x00303030),0.0); // 背景色
        this.renderer.setSize(elem.clientWidth, elem.clientHeight);
        elem.appendChild(this.renderer.domElement);
  
        this.scene = new THREE.Scene(); // 场景
        this.loader = new PCDLoader(); //PCD加载器
        const THIS = this
          //加载PCD文件
          if(this.pcdUrl){
            THIS.loader.load(
            // this.pcdUrl,
            this.pcdUrl,
            function (points) {
  
              points.geometry.rotateX(0.5 * Math.PI);//旋转模型，可调
              points.material.color = new THREE.Color(THIS.color); // 模型颜色
              THIS.pointcloud=points
  
              THIS.scene.add(points);
              var middle = new THREE.Vector3();
              // points.material = THIS.selectedPointMaterial;
              points.geometry.computeBoundingBox();
              points.geometry.boundingBox.getCenter(middle);
               // 构造盒子
              points.applyMatrix4(
                new THREE.Matrix4().makeTranslation(
                  -middle.x,
                  -middle.y,
                  -middle.z
                )
              );
              // 比例
              var largestDimension = Math.max(
                points.geometry.boundingBox.max.x,
                points.geometry.boundingBox.max.y,
                points.geometry.boundingBox.max.z
              );
              THIS.camera.position.y = largestDimension * 3;//相机位置，可调
              THIS.animate();
              //轨道控制器 旋转、平移、缩放
              THIS.controls = new OrbitControls(
                THIS.camera,
                THIS.renderer.domElement
              );
              THIS.controls.enableDamping = true;//旋转、平移开启阻尼
              THIS.controls.addEventListener("change", THIS.render); // 监听鼠标、键盘事件
               //放大缩小等
  
            },
              function (xhr) {
              let load = xhr.loaded / xhr.total
              if (load == 1) {
                THIS.loading = false
              }
            },
            function (error) {
              console.log(error);
            }
          );
          }
  
      },
      render () {
        this.renderer.render(this.scene, this.camera);
      },
      delete(){
        this.localMarkPoints=this.markPoints
      },
      cancel(){
        if(this.identifying){
          this.localMarkPoints=this.localMarkPoints.slice(0,-1);
        }
        console.log(this.identifying)
        console.log(this.markPoints)
        console.log(this.localMarkPoints)
        console.log(this.scene)
      },
      animate () {
        let delta = this.clock.getDelta();
        if (this.controls) {
          this.controls.update(delta);
        }
        this.animationId =requestAnimationFrame(this.animate)
        this.render();
      },
      async mpoint(){
        console.log(this.localMarkPoints)
        if(this.localMarkPoints&&this.localMarkPoints.length!=0){
          for(var i=0;i<this.localMarkPoints.length;i++){
        var sphereGeometry = new THREE.TetrahedronGeometry(0.02, 8, 8);
        var sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
        var selectedSphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
        const point = new THREE.Vector3( this.localMarkPoints[i].xPoints,this.localMarkPoints[i].yPoints,this.localMarkPoints[i].zPoints );
        selectedSphere.position.copy(point);
  
        this.scene.add(selectedSphere)
        var randomColor;
        if(this.localMarkPoints[i].isColor){
           randomColor = new THREE.Color(0xFF0000);
        }else{
          randomColor = new THREE.Color(Math.random(), Math.random(), Math.random());
        }
  
        selectedSphere.material.color = randomColor;
  
      }
        this.animate();
        }
  
      },
      onClick(event) {
        console.log(this.scene)
        //添加点云的双击
        if(this.isAdd){
          event.preventDefault();
        //判断当前点是否在图标内
        const container = document.getElementById('pcdcontainer');
        let getBoundingClientRect = container.getBoundingClientRect()
        this.mouse.x = (event.offsetX  / container.clientWidth) * 2 - 1;
        this.mouse.y = -(event.offsetY / container.clientHeight) * 2 + 1;
        const raycaster = new THREE.Raycaster();
        raycaster.near = 0; // 射线的起始距离
        raycaster.far = 100; // 射线的最大距离
        raycaster.params.Points.threshold = 0.1; // 设置点云的阈值
        raycaster.ray.direction.set(this.mouse.x, this.mouse.y, 0.5).unproject(this.camera).sub(this.camera.position).normalize();
        raycaster.setFromCamera(this.mouse, this.camera);
        const intersects = raycaster.intersectObject(this.scene );
        if (intersects.length <= 0) return void 0;
  
        let point = intersects[0].point;
  
        intersects[ 0 ].object.material.color.set( 0xff0000 );
  
  
        this.$emit('position',point)
  
        var sphereGeometry = new THREE.TetrahedronGeometry(0.02, 8, 8);
        var sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
        var selectedSphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
        selectedSphere.position.copy(point);
        // for (const markedPoint of this.scene.children){
        //   if(markedPoint instanceof THREE.Points){
        //     markedPoint
        //   }
        // }
        this.scene.add(selectedSphere)
        const clickedPoint = {
          xPoints: point.clone().x,
          yPoints: point.clone().y,
          zPoints: point.clone().z,
  
      };
      this.localMarkPoints.push(clickedPoint);
      var randomColor = new THREE.Color(Math.random(), Math.random(), Math.random());
      selectedSphere.material.color = randomColor;
        }
        else{
        event.preventDefault();
        const container = document.getElementById('pcdcontainer');
        this.mouse.x = (event.offsetX  / container.clientWidth) * 2 - 1;
        this.mouse.y = -(event.offsetY / container.clientHeight) * 2 + 1;
        const raycaster = new THREE.Raycaster();
        raycaster.setFromCamera(this.mouse, this.camera);
        const intersects = raycaster.intersectObject(this.scene);
        if (intersects.length <= 0) return void 0;
  
        let point = intersects[0].point;
        let clickedPoint = intersects[0].point;
        console.log(point)
        console.log(this.markPoints)
        //取已标记点最接近的点
        let closestPoint = null;
        let closestDistance = Infinity;
        for (const markedPoint of this.scene.children) {
          const markedVector = new THREE.Vector3(markedPoint.position
          .x, markedPoint.position
          .y,markedPoint.position
          .z);
          const distance = clickedPoint.distanceTo(markedVector);
  
          if (distance < closestDistance) {
            closestDistance = distance;
            closestPoint = markedPoint;
          }
        }
        if (closestPoint) {
          //把标记点变红
        var sphereGeometry = new THREE.TetrahedronGeometry(0.02, 8, 8);
        var sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xFF0000 });
        var selectedSphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
        selectedSphere=closestPoint
  
        var color = new THREE.Color(0xFF0000);
        selectedSphere.material.color = color;
        this.scene.add(selectedSphere)
        this.$emit('position',closestPoint)
        }
        }
      },
    },
  
    beforeDestroy() {
    clearTimeout(); // 这一行需要提供具体的定时器ID或函数，以清除定时器。例如：clearTimeout(this.timerId);
  
    try {
      // 清除场景中的子对象
      this.scene.children.forEach(child => {
        this.scene.remove(child);
      });
  
      // 释放渲染器的资源
      this.renderer.dispose();
      this.renderer.forceContextLoss(); // 不需要强制上下文丢失
      this.renderer.domElement = null;
  
      // 取消动画帧
      cancelAnimationFrame(this.animationId);
  
      // 关闭 WebGL 上下文
      const gl = this.renderer.context;
      if (gl) {
        const loseContextExtension = gl.getExtension("WEBGL_lose_context");
        if (loseContextExtension) {
          loseContextExtension.loseContext();
        }
      }
    } catch (e) {
      console.error("An error occurred during cleanup:", e);
    }
  
    // 清除 Three.js 缓存
    THREE.Cache.clear();
  },
    computed: {},
    watch: {
      markPoints (newValue) {
        console.log(newValue)
      // 当 markPoints prop 发生变化时，更新 localMarkPoints
      this.localMarkPoints = newValue.slice();
    },
    },
    filters: {},
    components: {}
  }
  </script>
  <style scoped lang='scss'>
  #pcdcontainer {
    width: 100%;
    height:100%;
  }
  </style>
  
  